/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable no-unused-vars */
/* eslint-disable @typescript-eslint/no-unused-vars */
import { computed, defineComponent, ref } from 'vue';
import { IResourceViewModel, ITaskViewModel } from '../../interface';
import { initStore } from '../../store';
import {
  useDrag,
  useVirtualScroll,
  useInitScheduleTable,
  useScheduleTableReSize,
  useScheduleTableStyle,
} from '../../hooks';
import { ScheduleTableEvent, ScheduleTableProps } from './schedule-table-type';
import { useScheduleToolbarEvent } from '../../hooks/use-schedule-table';
import './schedule-table.scss';
import { ScheduleToolbar } from '../schedule-toolbar/schedule-toolbar';

export const ScheduleTable = defineComponent({
  name: 'ScheduleTable',
  components: {
    'schedule-toolbar': ScheduleToolbar,
  },
  props: ScheduleTableProps,
  emits: ScheduleTableEvent,
  setup(props, { emit, slots }) {
    // 头部canvas实例
    const headerCanvas = ref<HTMLCanvasElement | null>(null);

    // 内容canvas实例
    const bodyCanvas = ref<HTMLCanvasElement | null>(null);

    // 坐标元素
    const coordinateElement = ref<HTMLDivElement | null>(null);

    // 初始化store
    initStore(props, emit as any);

    // 初始化表格
    const { resourceViewModels, taskViewModels } = useInitScheduleTable(
      headerCanvas,
      bodyCanvas,
      coordinateElement,
    );

    // 处理工具栏事件
    const { onRefresh, onSave, onSaveAs, onConfigRefresh } =
      useScheduleToolbarEvent(coordinateElement);

    // 计算表格样式
    const { headerStyle, bodyStyle } = useScheduleTableStyle(
      props,
      slots && !!slots.extraToolbar,
    );

    // 监听视图大小变化
    useScheduleTableReSize(props, headerCanvas, bodyCanvas, coordinateElement);

    // 虚拟滚动
    const { visibleRange, handleScroll } = useVirtualScroll(coordinateElement);

    // 拖拽
    const { handleDrop, handleDragOver, handleDragStart, handleDragLeave } =
      useDrag(props, coordinateElement, bodyCanvas);

    // 过滤可见的资源
    const visibleResourceViewModels = computed(() => {
      if (!resourceViewModels.value) return [];
      return resourceViewModels.value.slice(
        visibleRange.value.start,
        visibleRange.value.end,
      );
    });

    // 过滤可见的任务
    const visibleTaskViewModels = computed(() => {
      if (!taskViewModels.value) return [];
      return taskViewModels.value.filter((task: ITaskViewModel) => {
        const resourceIndex = props.resources.findIndex(
          res => res.id === task.resourceId,
        );
        return (
          resourceIndex >= visibleRange.value.start &&
          resourceIndex < visibleRange.value.end
        );
      });
    });

    return {
      bodyStyle,
      bodyCanvas,
      headerStyle,
      headerCanvas,
      visibleRange,
      coordinateElement,
      visibleTaskViewModels,
      visibleResourceViewModels,
      handleDrop,
      handleScroll,
      handleDragOver,
      handleDragStart,
      handleDragLeave,
      onRefresh,
      onSave,
      onSaveAs,
      onConfigRefresh,
    };
  },
  render() {
    return (
      <div class='schedule-table'>
        <div class='schedule-toolbar'>
          <schedule-toolbar
            onRefresh={this.onRefresh}
            onSaveAs={this.onSaveAs}
            onSave={this.onSave}
            onConfigChange={this.onConfigRefresh}
          ></schedule-toolbar>
          {this.$slots.extraToolbar ? (
            <div class='schedule-toolbar-extra'>
              {this.$slots.extraToolbar()}
            </div>
          ) : null}
        </div>
        <div class='schedule-table-header' style={this.headerStyle}>
          <canvas
            ref='headerCanvas'
            class='schedule-bg-layer schedule-table-header-canvas'
          ></canvas>
        </div>
        <div
          ref='coordinateElement'
          class='schedule-table-body'
          style={this.bodyStyle}
          onDrop={this.handleDrop}
          onScroll={this.handleScroll}
          onDragover={this.handleDragOver}
          onDragleave={this.handleDragLeave}
        >
          <canvas
            ref='bodyCanvas'
            class='schedule-bg-layer schedule-table-body-canvas'
          ></canvas>
          <div class='schedule-task-layer'>
            {this.visibleResourceViewModels.length > 0 ? (
              <>
                {this.visibleResourceViewModels.map(
                  (resourceViewModel: IResourceViewModel) => {
                    return (
                      <div
                        class='absolute-item resource-item'
                        data-resource-id={resourceViewModel.id}
                        style={{
                          width: `${resourceViewModel.width}px`,
                          height: `${resourceViewModel.height}px`,
                          top: `${resourceViewModel.top}px`,
                          left: `${resourceViewModel.left}px`,
                        }}
                      >
                        {resourceViewModel.data.name}
                      </div>
                    );
                  },
                )}
              </>
            ) : null}
            {this.visibleTaskViewModels.length > 0 ? (
              <>
                {this.visibleTaskViewModels.map(
                  (taskViewModel: ITaskViewModel) => {
                    return (
                      <div
                        draggable={this.allowDrag}
                        data-task-id={taskViewModel.id}
                        data-resource-id={taskViewModel.resourceId}
                        data-origin-task-id={taskViewModel.originalId}
                        style={{
                          width: `${taskViewModel.width}px`,
                          height: `${taskViewModel.height}px`,
                          top: `${taskViewModel.top}px`,
                          left: `${taskViewModel.left}px`,
                        }}
                        class={{
                          'absolute-item': true,
                          'task-item': true,
                          'is-draggable': this.allowDrag,
                        }}
                        onDragstart={evt =>
                          this.handleDragStart(
                            evt,
                            taskViewModel.originalId,
                            taskViewModel.data,
                          )
                        }
                      >
                        {taskViewModel.data.name}
                      </div>
                    );
                  },
                )}
              </>
            ) : null}
          </div>
        </div>
      </div>
    );
  },
});
